package com.cxz.study.logAop;

import com.cxz.study.loggerApi.BizLog;
import com.cxz.study.loggerApi.BizLogger;
import com.cxz.study.loggerApi.BizLoggerFactory;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.lang.reflect.Field;

/**
 * @className: BizLoggerInjector
 * @author: ocxz1
 * @date: 2025/6/17 下午11:48
 * @Version: 1.0
 * @description: ddd-struct3
 */
@Component
@Aspect
public class BizLoggerInjector implements ApplicationContextAware {

    private final BizLoggerFactory loggerFactory;
    private ApplicationContext applicationContext;

    public BizLoggerInjector(BizLoggerFactory loggerFactory) {
        this.loggerFactory = loggerFactory;
    }

    @Override
    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        this.applicationContext = ctx;
    }

    @PostConstruct
    public void injectLoggers() {
        for (Object bean : applicationContext.getBeansOfType(Object.class).values()) {
            injectLoggers(bean);
        }
    }

    /**
     * 注入BizLogger
     * @param bean
     */
    public void injectLoggers(Object bean) {
        Class<?> clazz = bean.getClass();

        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(BizLog.class)) {
                if (field.getType().equals(BizLogger.class)) {
                    BizLog annotation = field.getAnnotation(BizLog.class);
                    String category = annotation.value();

                    field.setAccessible(true);

                    try {
                        BizLogger logger;
                        if (category == null || category.isEmpty()) {
                            logger = loggerFactory.getLogger(clazz);
                        } else {
                            logger = loggerFactory.getLogger(clazz, category);
                        }

                        field.set(bean, logger);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException("Failed to inject BizLogger", e);
                    }
                }
            }
        }
    }
}
